import React, { memo, useEffect, useMemo, useRef } from 'react'
import { timeToMinutesAndSeconds, percentToSeconds, remainPlayTime } from '../../utils'
import styles from './index.module.scss'
import { useRecoilState, useRecoilValue } from 'recoil'
import {
  toggleControlShow,
  videoRefs,
  videoBufferTime,
  videoProgressStatus,
  videoCurrentTime,
  videoDuration
} from '../../store'

const Index = () => {
  const isControlShow = useRecoilValue(toggleControlShow) // 进度条显隐控制标识
  const { videoRef } = useRecoilValue(videoRefs) // video元素
  const [currentTime, setCurrentTime] = useRecoilState(videoCurrentTime) // 当前播放进度状态标识
  const duration = useRecoilValue(videoDuration) // 总进度
  const [progressState, dispatch] = useRecoilState(videoProgressStatus) // 鼠标移动进度展示框
  const bufferedTime = useRecoilValue(videoBufferTime) // 缓冲进度
  const isProgressHandleClicked = useRef(false) // 拖动进度手柄被启动标识
  const dragProgressRef = useRef(0) // 记录当前拖动进度数
  const progressSeekMaskRef = useRef(null) // 移动悬浮层元素

  // 已播放进度
  const calculateProcessPercent = useMemo(() => {
    return ((currentTime / duration) * 100).toString()
  }, [duration, currentTime])

  // 已缓冲进度
  const calculateBufferedPercent = useMemo(() => {
    return ((bufferedTime / duration) * 100).toString()
  }, [bufferedTime, duration])

  // 按下拖动进度手柄时回调
  const pausePlay = () => {
    isProgressHandleClicked.current = true
    videoRef.pause()
  }

  // 推拽播放进度
  const dragProgressVal = useMemo(
    () => percentToSeconds(progressState.progressPercent, duration),
    [progressState.progressPercent, duration]
  )

  // 移动进度悬浮层
  const popCurrentVideoImgBox = e => {
    e.stopPropagation()
    const seekPositionX = e.clientX - progressSeekMaskRef.current.getBoundingClientRect().left + 1
    const progressPercent = seekPositionX / progressSeekMaskRef.current.offsetWidth
    dispatch({
      ...progressState,
      progressPercent,
      isMovingProgress: true,
      positionX: seekPositionX
    })
  }
  //  隐藏进度悬浮层
  const hideCurrentVideoImgBox = e => {
    e.stopPropagation()
    dispatch({
      ...progressState,
      isMovingProgress: false
    })
  }
  //  点击进度条更改播放时间
  const getCurrentClickTime = e => {
    e.stopPropagation()
    videoRef.currentTime = dragProgressVal
  }

  // 拖动进度条的时候设置进度条进度
  useEffect(() => {
    if (isProgressHandleClicked.current) {
      const progress = dragProgressVal
      dragProgressRef.current = progress
      setCurrentTime(progress)
    }
  }, [progressState, isProgressHandleClicked.current])

  // 鼠标抬起的时候，恢复播放
  useEffect(() => {
    const mouseUp = () => {
      if (isProgressHandleClicked.current) {
        isProgressHandleClicked.current = false
        videoRef.currentTime = dragProgressRef.current
        videoRef.play()
        dragProgressRef.current = 0
      }
    }
    window.addEventListener('mouseup', mouseUp)
    return () => {
      window.removeEventListener('mouseup', mouseUp)
    }
  }, [videoRef])

  return (
    <div className={styles['progress-container']} style={{ opacity: isControlShow ? 1 : 0 }}>
      <div className={styles['progress-bg']}>
        {/* 缓冲进度 */}
        <div className={styles['progress-buffered']} style={{ width: `${calculateBufferedPercent}%` }}></div>
        {/* 已播放的进度 */}
        <div className={styles['progress-played']} style={{ width: `${calculateProcessPercent}%` }}></div>
        {/* 进度条拖动操作手柄 */}
        <div
          className={styles['progress-scrubber']}
          style={{ left: `${calculateProcessPercent}%` }}
          onMouseDown={pausePlay}
        ></div>
        {/* 点击切换进度 */}
        <div
          ref={progressSeekMaskRef}
          className={styles['progress-seek-mask']}
          onMouseMove={popCurrentVideoImgBox}
          onMouseLeave={hideCurrentVideoImgBox}
          onClick={getCurrentClickTime}
        ></div>
        {/* 确认当前所在播放进度 */}
        {progressState.isMovingProgress && (
          <span className={styles['video-current-time']} style={{ left: `${progressState.positionX}px` }}>
            {timeToMinutesAndSeconds(progressState.progressPercent, duration)}
          </span>
        )}
      </div>
      <p className={styles.duration}> {remainPlayTime(currentTime, duration)}</p>
    </div>
  )
}

export default memo(Index)
